package com.chat.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

public class DtoVoUtil {
    /**
     * 将一个entity对象转换成dto对象或者vo对象
     * 这个方法会用entity类的中与dto、vo类中的公共属性与属性值生成一个dto、vo对象返回
     * @param entity
     * @param dtoOrVoClass
     * @return
     * @param <T>
     * @param <E>
     */
    public static <T, E> T entityToDtoOrVo(E entity, Class<T> dtoOrVoClass) {
        //最终生成的Dto或Vo对象
        T t;
        try {
            //根据目标dto或vo的类形生成对象
            t = dtoOrVoClass.getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
        //dto或vo类的所有属性字段的名 的集合
        Set<String> dtoOrVoClassFieldNameSet = Arrays.stream(dtoOrVoClass.getDeclaredFields())
                .map(Field::getName)
                .collect(Collectors.toSet());
        //entity类的所有属性字段的名 的集合
        Set<String> entityClassFieldNameSet = Arrays.stream(entity.getClass().getDeclaredFields())
                .map(Field::getName)
                .collect(Collectors.toSet());
        // 求两个 Set 的交集，得到两个类共有的属性
        Set<String> intersection = new HashSet<>(dtoOrVoClassFieldNameSet);
        //交
        intersection.retainAll(entityClassFieldNameSet);
        //遍历交集对t进行赋值
        intersection.forEach(fieldName -> {
            try {
                Field entityField = entity.getClass().getDeclaredField(fieldName);
                entityField.setAccessible(true);
                Field dtoOrVoField = dtoOrVoClass.getDeclaredField(fieldName);
                dtoOrVoField.setAccessible(true);
                //从entity对象中取值 赋值到t对象中
                dtoOrVoField.set(t,entityField.get(entity));
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        });

        return t;
    }
}
